package contegor.scire.core.queries;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import contegor.scire.core.Connectable;
import contegor.scire.core.Container;
import contegor.scire.core.Id;
import contegor.scire.core.InfiniteSingletonList;
import contegor.scire.core.ReturnPoint;
import contegor.scire.core.ReturnPointAdapter;
import contegor.scire.core.Task;
import contegor.scire.core.TaskId;
import contegor.scire.core.Version;

/**
 * {@link Query} that fuses the result of many.
 *
 * @version $Revision: 1.4 $
 * @author  Héctor Cirbián Pousa ($Author: hector $)
 */
@Version("$Id: Union.java,v 1.4 2010-02-01 10:55:42 hector Exp $")
public class Union<I extends Connectable> extends QueryWithDependencies<I,I> {
  private static final long serialVersionUID = 4407093903652403231L;

  private Set<I> set = Collections.synchronizedSet(new HashSet<I>(dependencies.size()*2));
  private ReturnPoint<I> dependenciesReturnPoint = new ReturnPointAdapter<I>() {
    public <Y extends I> void manage(TaskId taskId, Y result) {
      set.add(result);
    }
    public <Y extends I> void manage(TaskId taskId, Collection<Y> result) {
      set.addAll(result);
    }
    public void manage(TaskId taskId, Exception exception) {
      returnPoint.manage(taskId, exception);
    }
  };

  public Union(Id targetContainerId, Query<I> ... dependencies) {
    super(targetContainerId, dependencies);
  }

  public void process(Container container) {
    returnPoint.manage(this.taskId, set);
  }

  @Override
  public List<? extends Task<I>> getDependencies() {
    return this.dependencies;
  }
 
  @Override
  public List<? extends ReturnPoint<I>> getDependenciesReturnPoints() {
    if (this.dependencies == null)
      return Collections.emptyList();
    return new InfiniteSingletonList<ReturnPoint<I>>(this.dependenciesReturnPoint, this.dependencies.size());
  }
}